home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 22 / Amiga Format AFCD22 (Jan 1998, Issue 106).iso / -seriously_amiga- / shareware / programming / other / modemlink / source / lib / link.c next >
C/C++ Source or Header  |  1997-11-05  |  8KB  |  351 lines

  1. /*
  2. ** NAME: Link.c
  3. ** DESC: Routines deaing with the modem link protocol and packets.  Many
  4. **       of the routines in this file are to be called by the user program.
  5. **       These routines will be linked into both the device and linked lib
  6. **       versions of modemlink.
  7. **
  8. ** AUTHOR:        DATE:       DESCRIPTION:
  9. ** ~~~~~~~~~~~~~~ ~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  10. ** Mike Veroukis  06 Apr 1997 Created
  11. */
  12.  
  13.  
  14. #include <exec/types.h>
  15. #include <exec/memory.h>
  16. #include <exec/io.h>
  17. #include <exec/ports.h>
  18. #include <devices/serial.h>
  19. #include <devices/timer.h>
  20. #include <dos/dosextens.h>
  21. #include <dos/dostags.h>
  22. #include <utility/tagitem.h>
  23.  
  24. #include <proto/dos.h>
  25. #include <proto/exec.h>
  26. #include <proto/utility.h>
  27.  
  28. #include <string.h>
  29. #include <stdio.h>
  30.  
  31. #include "Link.h"
  32. #include "CRC.h"
  33. #include "DeviceStuff.h"
  34. #include "ModemLinkAPI.h"
  35. #include "ModemLinkTask.h"
  36.  
  37. // These defines are used exclusively by the automatom in Establish()
  38. #define Q0 0
  39. #define Q1 1
  40. #define Q2 2
  41. #define Q3 3
  42. #define Qf 4
  43.  
  44. ULONG __saveds __asm
  45. ML_LaunchTask
  46. (
  47.   register __a0 struct IOExtLink *LinkIO,
  48.   register __a1 struct IOExtSer *SerIO
  49. )
  50. {
  51.   struct MsgPort *Port;
  52.   ULONG ResultCode = 0;
  53.   int i = 0;
  54.  
  55.   stcl_h(LinkIO->LinkProcName, LinkIO->Unit);
  56.   strcpy(LinkIO->LinkPortName, LinkIO->LinkProcName);
  57.   strins(LinkIO->LinkProcName, "LinkProc");
  58.   strins(LinkIO->LinkPortName, "LinkPort");
  59.  
  60.   Port = FindPort(LinkIO->LinkPortName);
  61.   if (!Port) {
  62.     CreateNewProcTags(
  63.         NP_Entry, AckTask,
  64.         NP_StackSize, 4096,
  65.         NP_Name, LinkIO->LinkProcName,
  66.         NP_Arguments, LinkIO->LinkPortName,
  67.         NP_CopyVars, TRUE,
  68.         TAG_END);
  69.  
  70.     do {
  71.       Delay(5);
  72.       Port = FindPort(LinkIO->LinkPortName);
  73.     } while (!Port && ++i < 20);
  74.  
  75.     if (Port) {
  76.       LinkIO->IOLink.io_Command = MLCMD_INIT;
  77.       LinkIO->IOLink.io_Data = (APTR)SerIO;
  78.       ML_BeginIO((struct IORequest *)LinkIO);
  79.       WaitIO((struct IORequest *)LinkIO);
  80.  
  81.       ResultCode++;
  82.     }
  83.   }
  84.  
  85.   return(ResultCode);
  86. }
  87.  
  88. ULONG __saveds __asm
  89. ML_EstablishTagList
  90. (
  91.   register __a0 struct IOExtLink *LinkIO,
  92.   register __a1 struct IOExtSer *SerIO,
  93.   register __a2 struct TagItem *tagList
  94. )
  95. {
  96.   struct timerequest *TimerIO = NULL;
  97.   struct MsgPort *TimerMP = NULL;
  98.   ULONG ReturnStatus;
  99.   char ACKStates[4] = {Q3, Q3, Qf, Q3};
  100.   char ENQStates[4] = {Q2, Q2, Q2, Qf};
  101.   char buf[3] = {ENQ, ACK, 0};
  102.   char State = Q0;
  103.  
  104.   if (OpenTimerDevice(&TimerMP, &TimerIO)) {
  105.     TimerIO->tr_node.io_Command = TR_ADDREQUEST;
  106.     TimerIO->tr_time.tv_secs = 5;
  107.     TimerIO->tr_time.tv_micro = 0;
  108.     SendIO((struct IORequest *) TimerIO);
  109.  
  110.     SerIO->IOSer.io_Command = CMD_WRITE;
  111.     SerIO->IOSer.io_Length = 1;
  112.     SerIO->IOSer.io_Data = &(buf[0]);
  113.     DoIO((struct IORequest *) SerIO);
  114.  
  115.     State = Q1;
  116.  
  117.     while (State != Qf) {
  118.       SerIO->IOSer.io_Command = CMD_READ;
  119.       SerIO->IOSer.io_Length = 1;
  120.       SerIO->IOSer.io_Data = &(buf[2]);
  121.  
  122.       if (TimedIO((struct IORequest *) SerIO, 1)) {
  123.         if (buf[2] == ACK)
  124.           State = ACKStates[State];
  125.         else if (buf[2] == ENQ) {
  126.           SerIO->IOSer.io_Command = CMD_WRITE;
  127.           SerIO->IOSer.io_Length = 1;
  128.           SerIO->IOSer.io_Data = &(buf[1]);
  129.           DoIO((struct IORequest *) SerIO);
  130.  
  131.           State = ENQStates[State];
  132.         }
  133.       }
  134.       else if (State == Q1 || State == Q2) {
  135.         SerIO->IOSer.io_Command = CMD_WRITE;
  136.         SerIO->IOSer.io_Length = 1;
  137.         SerIO->IOSer.io_Data = &(buf[0]);
  138.         DoIO((struct IORequest *) SerIO);
  139.       }
  140.  
  141.       if (CheckIO((struct IORequest *) TimerIO))
  142.         break;
  143.     }
  144.  
  145.     if (!CheckIO((struct IORequest *) TimerIO))
  146.       AbortIO((struct IORequest *) TimerIO);
  147.     WaitIO((struct IORequest *) TimerIO);
  148.  
  149.     SafeCloseDevice(TimerMP, (struct IORequest *)TimerIO);
  150.   }
  151.  
  152.   if (State == Qf)
  153.     if (ML_LaunchTask(LinkIO, SerIO))
  154.       ReturnStatus = EstErr_OK;
  155.     else
  156.       ReturnStatus = EstErr_TASK_ERR;
  157.   else
  158.     ReturnStatus = EstErr_TIMEOUT;
  159.  
  160.   return(ReturnStatus);
  161. }
  162.  
  163. void __saveds __asm
  164. ML_Terminate
  165. (
  166.   register __a0 struct IOExtLink *LinkIO
  167. )
  168. {
  169.   struct Task *LinkProc;
  170.  
  171.   if (LinkIO && (LinkProc = FindTask(LinkIO->LinkProcName))) {
  172.     Signal((struct Task *)LinkProc, SIGBREAKF_CTRL_C);
  173.  
  174.     do {
  175.       Delay(10);
  176.     } while (FindTask(LinkIO->LinkProcName));
  177.   }
  178. }
  179.  
  180. struct LinkPkt __saveds __asm
  181. *ML_AllocPkt(void)
  182. {
  183.   struct LinkPkt *Pkt;
  184.   if (Pkt =  (struct LinkPkt *)AllocMem(sizeof(struct LinkPkt), MEMF_PUBLIC | MEMF_CLEAR)) {
  185.     Pkt->Data = NULL;
  186.     Pkt->Length = 0;
  187.   }
  188.  
  189.   return Pkt;
  190. }
  191.  
  192. void __saveds __asm
  193. ML_FreePkt
  194. (
  195.   register __a0 struct LinkPkt *Pkt
  196. )
  197. {
  198.   if (Pkt) {
  199.     if (Pkt->Data && (Pkt->Length > 0))
  200.       FreeMem(Pkt->Data, Pkt->Length);
  201.     FreeMem(Pkt, sizeof(struct LinkPkt));
  202.   }
  203. }
  204.  
  205. void __saveds __asm
  206. ML_FreePktList
  207. (
  208.   register __a0 struct MinList *PktList
  209. )
  210. {
  211.   struct LinkPkt *Pkt, *TmpPkt;
  212.  
  213.   if (PktList) {
  214.     Pkt = (struct LinkPkt *)PktList->mlh_Head;
  215.  
  216.     while (Pkt->ml_Node.mln_Succ) {
  217.       TmpPkt = (struct LinkPkt *)Pkt->ml_Node.mln_Succ;
  218.       ML_FreePkt(Pkt);
  219.       Pkt = TmpPkt;
  220.     }
  221.   }
  222. }
  223.  
  224.  
  225. ULONG __saveds __asm
  226. ML_PacketizeData
  227. (
  228.   register __a0 struct MinList *PktList,
  229.   register __a1 UBYTE *Data,
  230.   register __d0 ULONG Length,
  231.   register __d1 ULONG PktSize
  232. )
  233. {
  234.   struct LinkPkt *tmp;
  235.  
  236.   if (PktSize <= 0)
  237.     PktSize = Length;
  238.  
  239.   while (Length > 0) {
  240.     if (tmp = ML_AllocPkt()) {
  241.       tmp->Length = PktSize;
  242.       if (tmp->Data = AllocMem(PktSize, MEMF_CLEAR | MEMF_PUBLIC)) {
  243.         CopyMem(Data, tmp->Data, PktSize);
  244.         Length -= PktSize;
  245.  
  246.         if (PktSize > Length)
  247.           PktSize = Length;
  248.         Data += PktSize;
  249.  
  250.         AddTail((struct List *)PktList, (struct Node *)tmp);
  251.       }
  252.       else {
  253.         FreeMem(tmp, sizeof(struct LinkPkt));
  254.         tmp = NULL;
  255.       }
  256.     }
  257.     if (!tmp) {
  258.       while (tmp = (struct LinkPkt *) RemHead((struct List *)PktList)) {
  259.         if (tmp->Data)
  260.           FreeMem(tmp->Data, tmp->Length);
  261.         FreeMem(tmp, sizeof(struct LinkPkt));
  262.       }
  263.       Length = -1L;
  264.     }
  265.   }
  266.  
  267.   return (ULONG)(Length == 0);
  268. }
  269.  
  270. ULONG __saveds __asm
  271. ML_DePacketizeData
  272. (
  273.   register __a0 struct MinList *PktList,
  274.   register __a1 UBYTE *Data,
  275.   register __d0 ULONG Length
  276. )
  277. {
  278.   struct LinkPkt *Pkt;
  279.   ULONG TotalSize = 0L;
  280.   ULONG PktSize;
  281.   UBYTE *CurBuf = Data;
  282.  
  283.   if (PktList && Data && Length) {
  284.     Pkt = (struct LinkPkt *)PktList->mlh_Head;
  285.  
  286.     while (Length > 0 && Pkt->ml_Node.mln_Succ) {
  287.       PktSize = Pkt->Length;
  288.  
  289.       if (PktSize > Length)
  290.         PktSize = Length;
  291.  
  292.       CopyMem(Pkt->Data, CurBuf, PktSize);
  293.  
  294.       Length -= PktSize;
  295.       CurBuf += PktSize;
  296.       TotalSize += PktSize;
  297.  
  298.       Pkt = (struct LinkPkt *)Pkt->ml_Node.mln_Succ;
  299.     }
  300.   }
  301.  
  302.   return(TotalSize);
  303. }
  304.  
  305. ULONG __saveds __asm
  306. ML_PacketDataSize
  307. (
  308.   register __a0 struct MinList *PktList
  309. )
  310. {
  311.   struct LinkPkt *Pkt;
  312.   ULONG TotalSize = 0L;
  313.  
  314.   if (PktList) {
  315.     Pkt = (struct LinkPkt *)PktList->mlh_Head;
  316.  
  317.     while (Pkt->ml_Node.mln_Succ) {
  318.       TotalSize += Pkt->Length;
  319.       Pkt = (struct LinkPkt *)Pkt->ml_Node.mln_Succ;
  320.     }
  321.   }
  322.  
  323.   return(TotalSize);
  324. }
  325.  
  326. struct IOExtLink *ML_GetMsg(struct MsgPort *MPort, ULONG PipeBit)
  327. {
  328.   struct IOExtLink *LinkIO;
  329.  
  330.   Forbid();
  331.  
  332.   if (LinkIO = (struct IOExtLink *)GetMsg(MPort))
  333.     LinkIO->Flags = (LinkIO->Flags & (~ML_PIPE2)) | PipeBit;
  334.  
  335.   Permit();
  336.  
  337.   return (LinkIO);
  338. }
  339.  
  340. void ML_ReplyMsg(struct IOExtLink *LinkReq)
  341. {
  342.   Forbid();
  343.  
  344.   if (LinkReq) {
  345.     LinkReq->Flags &= ~ML_PIPE2;
  346.     ReplyMsg((struct Message *)LinkReq);
  347.   }
  348.  
  349.   Permit();
  350. }
  351.